package ar.com.jendrix.common.web;

import javax.faces.event.ActionEvent;

import org.primefaces.context.RequestContext;

import ar.com.jendrix.common.exception.ApplicationException;
import ar.com.jendrix.common.exception.SystemException;
import ar.com.jendrix.common.exception.ValidationException;
import ar.com.jendrix.common.web.action.ActionEntityType;
import ar.com.jendrix.common.web.util.JSFNavigationRules;

@SuppressWarnings("serial")
public abstract class ManagerBaseBean extends SearchBean {

	private ActionEntityType action;

	/**
	 * 
	 * @return
	 */
	protected final ActionEntityType getAction() {
		return action;
	}

	/**
	 * 
	 */
	@Override
	protected void clear() throws ApplicationException, SystemException {
		super.clear();
		this.action = null;
	}

	/**
	 * 
	 * @return
	 */
	public final String add() {
		action = ActionEntityType.ADD;
		String outcome = JSFNavigationRules.addFailure.name();
		try {
			doAdd();
			outcome = JSFNavigationRules.addSuccess.name();
		} catch (ApplicationException a) {
			addErrorMessages(a.getMessages());
		} catch (Throwable t) {
			log.error(t.getMessage(), t);
			addErrorMessage("Error al iniciar accion agregar");
		}
		return outcome;
	}

	/**
	 * 
	 * @param actionEvent
	 */
	public final void add(ActionEvent actionEvent) {
		action = ActionEntityType.ADD;
		RequestContext.getCurrentInstance().addCallbackParam("action", false);
		try {
			doAdd();
			RequestContext.getCurrentInstance().addCallbackParam("action", true);
		} catch (ApplicationException a) {
			addErrorMessages(a.getMessages());
		} catch (Throwable t) {
			log.error(t.getMessage(), t);
			addErrorMessage("Error al iniciar accion agregar");
		}
	}

	/**
	 * 
	 * @throws ApplicationException
	 * @throws SystemException
	 */
	protected abstract void doAdd() throws ApplicationException, SystemException;

	/**
	 * 
	 * @return
	 */
	public final String edit() {
		action = ActionEntityType.EDIT;
		String outcome = JSFNavigationRules.editFailure.name();
		try {
			doEdit();
			outcome = JSFNavigationRules.editSuccess.name();
		} catch (ApplicationException a) {
			addErrorMessages(a.getMessages());
		} catch (Throwable t) {
			log.error(t.getMessage(), t);
			addErrorMessage("Error al iniciar accion editar");
		}
		return outcome;
	}

	/**
	 * 
	 * @param actionEvent
	 */
	public final void edit(ActionEvent actionEvent) {
		action = ActionEntityType.EDIT;
		RequestContext.getCurrentInstance().addCallbackParam("action", false);
		try {
			doEdit();
			RequestContext.getCurrentInstance().addCallbackParam("action", true);
		} catch (ApplicationException a) {
			addErrorMessages(a.getMessages());
		} catch (Throwable t) {
			log.error(t.getMessage(), t);
			addErrorMessage("Error al iniciar accion editar");
		}
	}

	/**
	 * 
	 * @throws ApplicationException
	 * @throws SystemException
	 */
	protected abstract void doEdit() throws ApplicationException, SystemException;

	/**
	 * 
	 * @return
	 */
	public final String delete() {
		action = ActionEntityType.DELETE;
		String outcome = JSFNavigationRules.deleteFailure.name();
		try {
			doDelete();
			outcome = JSFNavigationRules.deleteSuccess.name();
		} catch (ApplicationException a) {
			addErrorMessages(a.getMessages());
		} catch (Throwable t) {
			log.error(t.getMessage(), t);
			addErrorMessage("Error al iniciar accion eliminar");
		}
		return outcome;
	}

	/**
	 * 
	 * @param actionEvent
	 */
	public final void delete(ActionEvent actionEvent) {
		action = ActionEntityType.DELETE;
		RequestContext.getCurrentInstance().addCallbackParam("action", false);
		try {
			doDelete();
			RequestContext.getCurrentInstance().addCallbackParam("action", true);
		} catch (ApplicationException a) {
			addErrorMessages(a.getMessages());
		} catch (Throwable t) {
			log.error(t.getMessage(), t);
			addErrorMessage("Error al iniciar accion eliminar");
		}
	}

	/**
	 * 
	 * @throws ApplicationException
	 * @throws SystemException
	 */
	protected abstract void doDelete() throws ApplicationException, SystemException;

	/**
	 * 
	 * @return
	 */
	public final String confirmAdd() {
		String outcome = JSFNavigationRules.confirmAddFailure.name();
		try {
			doConfirmAdd();
			doAddSuccess();
			clear();
			outcome = JSFNavigationRules.confirmAddSuccess.name();
		} catch (ValidationException v) {
			addValidationMessages(v.getMessages());
		} catch (ApplicationException a) {
			addErrorMessages(a.getMessages());
		} catch (Throwable t) {
			log.error(t.getMessage(), t);
			addErrorMessage("Error al generar registro");
		}
		return outcome;
	}

	/**
	 * 
	 * @param actionEvent
	 */
	public final void confirmAdd(ActionEvent actionEvent) {
		RequestContext.getCurrentInstance().addCallbackParam("action", false);
		try {
			doConfirmAdd();
			doAddSuccess();
			clear();
			RequestContext.getCurrentInstance().addCallbackParam("action", true);
		} catch (ValidationException v) {
			addValidationMessages(v.getMessages());
		} catch (ApplicationException a) {
			addErrorMessages(a.getMessages());
		} catch (Throwable t) {
			log.error(t.getMessage(), t);
			addErrorMessage("Error al generar registro");
		}
	}

	/**
	 * 
	 * @throws ValidationException
	 * @throws ApplicationException
	 * @throws SystemException
	 */
	protected abstract void doConfirmAdd() throws ValidationException, ApplicationException, SystemException;

	/**
	 * 
	 * @return
	 */
	public final String confirmEdit() {
		String outcome = JSFNavigationRules.confirmEditFailure.name();
		try {
			doConfirmEdit();
			doEditSuccess();
			clear();
			outcome = JSFNavigationRules.confirmEditSuccess.name();
		} catch (ValidationException v) {
			addValidationMessages(v.getMessages());
		} catch (ApplicationException a) {
			addErrorMessages(a.getMessages());
		} catch (Throwable t) {
			log.error(t.getMessage(), t);
			addErrorMessage("Error al editar registro");
		}
		return outcome;
	}

	/**
	 * 
	 * @param actionEvent
	 */
	public final void confirmEdit(ActionEvent actionEvent) {
		RequestContext.getCurrentInstance().addCallbackParam("action", false);
		try {
			doConfirmEdit();
			doEditSuccess();
			clear();
			RequestContext.getCurrentInstance().addCallbackParam("action", true);
		} catch (ValidationException v) {
			addValidationMessages(v.getMessages());
		} catch (ApplicationException a) {
			addErrorMessages(a.getMessages());
		} catch (Throwable t) {
			log.error(t.getMessage(), t);
			addErrorMessage("Error al editar registro");
		}
	}

	/**
	 * 
	 * @throws ValidationException
	 * @throws ApplicationException
	 * @throws SystemException
	 */
	protected abstract void doConfirmEdit() throws ValidationException, ApplicationException, SystemException;

	/**
	 * 
	 * @return
	 */
	public final String confirmDelete() {
		String outcome = JSFNavigationRules.confirmDeleteFailure.name();
		try {
			doConfirmDelete();
			doDeleteSuccess();
			clear();
			outcome = JSFNavigationRules.confirmDeleteSuccess.name();
		} catch (ApplicationException a) {
			addErrorMessages(a.getMessages());
		} catch (Throwable t) {
			log.error(t.getMessage(), t);
			addErrorMessage("Error al eliminar registro");
		}
		return outcome;
	}

	/**
	 * 
	 * @param actionEvent
	 */
	public final void confirmDelete(ActionEvent actionEvent) {
		RequestContext.getCurrentInstance().addCallbackParam("action", false);
		try {
			doConfirmDelete();
			doDeleteSuccess();
			clear();
			RequestContext.getCurrentInstance().addCallbackParam("action", true);
		} catch (ApplicationException a) {
			addErrorMessages(a.getMessages());
		} catch (Throwable t) {
			log.error(t.getMessage(), t);
			addErrorMessage("Error al eliminar registro");
		}
	}

	/**
	 * 
	 */
	protected void doDeleteSuccess() {
	}

	/**
	 * 
	 * @throws ApplicationException
	 * @throws SystemException
	 */
	protected abstract void doConfirmDelete() throws ApplicationException, SystemException;

	/**
	 * 
	 * @return
	 */
	public final String save() {
		String outcome = JSFNavigationRules.saveFailure.name();
		try {
			doSave();
			if (ActionEntityType.ADD.equals(getAction())) {
				doAddSuccess();
			} else {
				doEditSuccess();
			}
			clear();
			outcome = JSFNavigationRules.saveSuccess.name();
		} catch (ValidationException v) {
			addValidationMessages(v.getMessages());
		} catch (ApplicationException a) {
			addErrorMessages(a.getMessages());
		} catch (Throwable t) {
			log.error(t.getMessage(), t);
			addErrorMessage("Error al grabar registro");
		}
		return outcome;
	}

	/**
	 * 
	 */
	protected void doAddSuccess() {
	}

	/**
	 * 
	 */
	protected void doEditSuccess() {
	}

	/**
	 * 
	 * @param actionEvent
	 */
	public final void save(ActionEvent actionEvent) {
		RequestContext.getCurrentInstance().addCallbackParam("action", false);
		try {
			doSave();
			if (ActionEntityType.ADD.equals(getAction())) {
				doAddSuccess();
			} else {
				doEditSuccess();
			}
			clear();
			RequestContext.getCurrentInstance().addCallbackParam("action", true);
		} catch (ValidationException v) {
			addValidationMessages(v.getMessages());
		} catch (ApplicationException a) {
			addErrorMessages(a.getMessages());
		} catch (Throwable t) {
			log.error(t.getMessage(), t);
			addErrorMessage("Error al generar registro");
		}
	}

	/**
	 * 
	 * @throws ValidationException
	 * @throws ApplicationException
	 * @throws SystemException
	 */
	protected abstract void doSave() throws ValidationException, ApplicationException, SystemException;

	/**
	 * 
	 * @return
	 */
	public final String cancel() {
		String outcome = JSFNavigationRules.cancelFailure.name();
		try {
			doCancel();
			clear();
			outcome = JSFNavigationRules.cancelSuccess.name();
		} catch (ApplicationException a) {
			addErrorMessages(a.getMessages());
		} catch (Throwable t) {
			log.error(t.getMessage(), t);
			addErrorMessage("Error al cancelar accion");
		}
		return outcome;
	}

	/**
	 * 
	 * @param actionEvent
	 */
	public final void cancel(ActionEvent actionEvent) {
		RequestContext.getCurrentInstance().addCallbackParam("action", false);
		try {
			doCancel();
			clear();
			RequestContext.getCurrentInstance().addCallbackParam("action", true);
		} catch (ApplicationException a) {
			addErrorMessages(a.getMessages());
		} catch (Throwable t) {
			log.error(t.getMessage(), t);
			addErrorMessage("Error al cancelar accion");
		}
	}

	/**
	 * 
	 * @throws ApplicationException
	 * @throws SystemException
	 */
	protected void doCancel() throws ApplicationException, SystemException {
		log.info("cancel");
	}

	/**
	 * 
	 * @return
	 */
	public final boolean isActionAdd() {
		return ActionEntityType.ADD.equals(getAction());
	}
}